#include "input.h"
#include "color.h"
#include "vector3d.h"
#include "particle.h"
#include "spring.h"
#include "defines/inputSpringType.h"

#include <QTextStream>
#include <string>
#include <utility>
#include <fstream>

Input::Input() : QObject()
{
    file = NULL;
    playbackFile = NULL;
//    posInPlayback = -1;
    timeInPlayback = 0;
    timer = new QTimer(this);
    playbackEnd = false;
}

Input::~Input()
{
    delete file;
    delete playbackFile;
    delete timer;

    for(unsigned int i = 0; i < playbackFabrics.size(); i++){
        if(playbackFabrics.at(i)) delete playbackFabrics.at(i);
    }
    playbackFabrics.clear();
}

std::vector<Fabric *> Input::parse(QFile* _file, unsigned int _adjacency, double *_deltaT, double *_g)
{

    QString suffix = QFileInfo(*_file).suffix();

    file = _file;

    if(suffix == "ca") return CAparse(_deltaT, _g);

    if(suffix == "obj") return OBJparse(_adjacency);


    std::vector<Fabric *> vectorFabric;

    return vectorFabric;
}

std::vector<Fabric *> *Input::parse(QFile* _file)
{
    QString suffix = QFileInfo(*_file).suffix();

    playbackFile = _file;
    return playbackParse();

}

//arquivo sem ser OBJ
std::vector<Fabric *> Input::CAparse(double *_deltaT, double *_g)
{
    std::cout <<"TEM QUE ACJEITAR O PARCERT DO CA!" <<std::endl;
	char type;

    Color currentColor(1.0, 1.0, 1.0, 1.0);

	double r, g, b, alpha;

	double x, y, z, k, ks, kd;

	int IDpBegin, IDpEnd, fx, fy, fz, dof = 0, v1, v2, v3;

	Particle *pBegin, *pEnd;

	Spring *s;

	Face *f;

	std::vector<Particle *> particles;

	std::vector<Spring *> springs;

	std::vector<Face *> faces;

	std::vector<int> refVector;

	std::vector<double> kVector;

	unsigned int idFabric = 0;

	unsigned int idParticle = 0;

	unsigned int idSpring = 0;

	unsigned int idFace = 0;

	QTextStream stream(file);

	while(stream >> type, !stream.atEnd())
	{
		if(type == 'p')
		{
			stream >> x >> y >> z >> fx >> fy >> fz;

			particles.push_back(new Particle(idParticle++, Vector3D(x, y, z), currentColor));

            if(fx != -1) refVector.push_back(dof++);

            else refVector.push_back(-1);

            if(fy != -1) refVector.push_back(dof++);

            else refVector.push_back(-1);

            if(fz != -1) refVector.push_back(dof++);

            else refVector.push_back(-1);

			continue;

		}
        else if(type == 's')
        {
            //mola estrutural (Structural)

			stream >> IDpBegin >> IDpEnd >> ks >> kd;

			pBegin = particles.at(IDpBegin);

			pEnd = particles.at(IDpEnd);

			s = new Spring(idSpring++, STRUCTURAL_HORIZONTAL, kVector.at(ks), kVector.at(kd), pBegin, pEnd, currentColor);

			springs.push_back(s);

            s->addParticleMass(pBegin, pEnd);

			continue;
		}
		else if(type == 'h')
		{
		    //mola de cisalhamento (sHear)

			stream >> IDpBegin >> IDpEnd >> ks >> kd;

			pBegin = particles.at(IDpBegin);

			pEnd = particles.at(IDpEnd);

			s = new Spring(idSpring++, SHEAR, kVector.at(ks), kVector.at(kd), pBegin, pEnd, currentColor);

			springs.push_back(s);

            s->addParticleMass(pBegin, pEnd);

			continue;
		}
		else if(type == 'b')
		{
		    //mola de flexão (Bend)

			stream >> IDpBegin >> IDpEnd >> ks >> kd;

			pBegin = particles.at(IDpBegin);

			pEnd = particles.at(IDpEnd);

			s = new Spring(idSpring++, FLEXION, kVector.at(ks), kVector.at(kd), pBegin, pEnd, currentColor);

			springs.push_back(s);

            s->addParticleMass(pBegin, pEnd);

			continue;
		}
		else if(type == 'f')
		{
			stream >> v1 >> v2 >> v3;

            f = new Face(idFace++);

            Particle *p1 = particles.at(v1);
            Particle *p2 = particles.at(v2);
            Particle *p3 = particles.at(v3);

            f->addParticle(p1);
            f->addParticle(p2);
            f->addParticle(p3);

            p1->addFace(f);
            p2->addFace(f);
            p3->addFace(f);

			faces.push_back(f);

			continue;
		}
		else if(type == 'c')
		{
			stream >> r >> g >> b >> alpha;

			currentColor = Color(r, g, b, alpha);

			continue;
		}
		else if(type == 'k')
		{
			stream >> k;

			kVector.push_back(k);

			continue;
		}
		else if(type == '#')
		{
			//Comments!
			stream.readLine();

			continue;
		}
		else if(type == 't')
		{
			//Comments!
			stream >> *_deltaT;

			continue;
		}
		 else if(type == 'g')
        {
			//Comments!
			stream >> *_g;

			continue;
		}
	}

	std::cout << "existem " <<particles.size() <<" massas e " << springs.size()<< " molas."<<std::endl;

	std::vector<Fabric *> fabrics;
	fabrics.push_back(new Fabric(idFabric++, particles, springs, faces, dof, toMatrixNx3(idParticle, refVector)));

	return fabrics;
}

std::vector<Fabric *> Input::OBJparse(unsigned int _adjacency)
{
	QString type;

    Color particleColor(1.0, 1.0, 0.0, 1.0);

    Color structuralSpringColor(0.0, 1.0, 0.0, 1);
    Color shearSpringColor(0.0, 1.0, 1.0, 1);
    Color flexionSpringColor(0.0, 0.0, 1.0, 1);


//    double kdParticle = 0.01;

    //tecido teste
	//double ksStructural = 2200.0, kdStructural = 2.0;
	//double ksShear =50.0, kdShear = 1.0;
	//double ksFlexion = 0.05, kdFlexion = 0.005;
//
//	double ksStructural = 2200.0, kdStructural = 2.0;
//	double ksShear = 50.0, kdShear = 1.0;
//	double ksFlexion = 2.0, kdFlexion = 0.005;

	/*double ksStructural = 2200.0, kdStructural = 2.0;
	double ksShear =50.0, kdShear = 1.0;
	double ksFlexion = 2.0, kdFlexion = 0.005;*/

    //tecido oxford
	/*double ksStructural = 2445.0, kdStructural = 2.8;
	double ksShear = 1467.0, kdShear = 2.0;
	double ksFlexion = 449.0, kdFlexion = 0.5;*/

    //tecido cetim
//	double ksStructural = 4890.0, kdStructural = 5.0;
//	double ksShear = 2934.0, kdShear = 1.5;
//	double ksFlexion = 978.0, kdFlexion = 0.1;

    //algodao com elastano (2)
//	double ksStructural = 287.65, kdStructural = 5.0;
//	double ksShear = 172.59, kdShear = 1.5;
//	double ksFlexion = 57.53, kdFlexion = 0.1;

    //algodao com elastano (1)
//	double ksStructural = 1222.5, kdStructural = 5.0;
//	double ksShear = 733.5, kdShear = 1.5;
//	double ksFlexion = 244.5, kdFlexion = 0.1;

    //fazer um dlg perguntnaod as contanstes antes de ler o arquivo, e o deltaT. ***
    //depois fazer alo pra se poder escolher os pontos presos

    bool added;

	double x, y, z;

	int dof = 0, v1, v2, v3, v4, t1, t2, t3, t4;

	Particle *pBegin, *pEnd;

	Spring *s;

	Face *f1, *f2;

	std::vector<Particle *> particles;

	std::vector<Spring *> structuralVerticalSprings;

	std::vector<Spring *> structuralHorizontalSprings;

	std::vector<Spring *> shearSprings;

	std::vector<Spring *> flexionSprings;

	std::vector<Face *> faces;

	std::vector<int> refVector;

    std::vector< std::pair<double, double> > textureCoord;

	std::vector<double> kVector;

	unsigned int idFabric = 0;

	unsigned int idParticle = 0;

	unsigned int idSpring = 0;

	unsigned int idFace = 0;

	bool hasTextureCoord = false;

	QTextStream stream(file);

	while(stream >> type, !stream.atEnd())
	{
		if(type == "v")
		{
			stream >> x >> y >> z;

			particles.push_back(new Particle(idParticle++, Vector3D(x, y, z), particleColor));

            //so para fazer, mas REF terá que ser refeito colocando os pontos presos

            refVector.push_back(dof++);
            refVector.push_back(dof++);
            refVector.push_back(dof++);

//           if(idParticle -1 !=10 && idParticle -1 != 1)
////           if(idParticle -1 !=0 && idParticle -1 != 1)
//           {
//                refVector.push_back(dof++);
//                refVector.push_back(dof++);
//                refVector.push_back(dof++);
//           }
//           else
//           {
//               refVector.push_back(-1);
//               refVector.push_back(-1);
//               refVector.push_back(-1);
//           }


			continue;
		}else if(type == "vt")
        {
            double u, v;
            stream >> u >> v;

            textureCoord.push_back( std::make_pair(u, v) );

            hasTextureCoord = true;
        }
		else if(type == "f")
        {
//			stream >> v1 >> v2 >> v3 >> v4;

            QString token;

            stream >> token;
            int count = sscanf(token.toStdString().c_str(), "%d/%d", &v1, &t1);

            stream >> token;
            count = sscanf(token.toStdString().c_str(), "%d/%d", &v2, &t2);

            stream >> token;
            count = sscanf(token.toStdString().c_str(), "%d/%d", &v3, &t3);

            stream >> token;
            count = sscanf(token.toStdString().c_str(), "%d/%d", &v4, &t4);

			Particle *p1 = particles.at(v1 - 1);
			Particle *p2 = particles.at(v2 - 1);
			Particle *p3 = particles.at(v3 - 1);
			Particle *p4 = particles.at(v4 - 1);

            if(hasTextureCoord)
            {
                p1->setTextureCoord(textureCoord[t1 - 1].first, textureCoord[t1 - 1].second);
                p2->setTextureCoord(textureCoord[t2 - 1].first, textureCoord[t2 - 1].second);
                p3->setTextureCoord(textureCoord[t3 - 1].first, textureCoord[t3 - 1].second);
                p4->setTextureCoord(textureCoord[t4 - 1].first, textureCoord[t4 - 1].second);
            }

            f1 = new Face(idFace++);
            f1->addParticle(p1);//OBJ começa a contar a partir do 1
            f1->addParticle(p2);
            f1->addParticle(p4);

            p1->addFace(f1);
            p2->addFace(f1);
            p4->addFace(f1);

            faces.push_back(f1);

            f2 = new Face(idFace++);
            f2->addParticle(p2);
            f2->addParticle(p3);
            f2->addParticle(p4);

            p2->addFace(f2);
            p3->addFace(f2);
            p4->addFace(f2);

            faces.push_back(f2);


            f1 = new Face(-1);
            f1->addParticle(p1);
            f1->addParticle(p2);
            f1->addParticle(p3);

            p1->addFace(f1);
            p2->addFace(f1);
            p3->addFace(f1);

            f2 = new Face(-2);
            f2->addParticle(p1);
            f2->addParticle(p3);
            f2->addParticle(p4);

            p1->addFace(f2);
            p3->addFace(f2);
            p4->addFace(f2);


			//criando molas estruturais e de cisalhamento
            //estruturais

            pBegin = p1;

            pEnd = p2;

            added = createSpring(pBegin, pEnd, &structuralHorizontalSprings, idSpring, structuralSpringColor, STRUCTURAL_HORIZONTAL);

            if(added)
            {
                idSpring = idSpring + 1;
            }

            pBegin = p2;

            pEnd = p3;

            added = createSpring(pBegin, pEnd, &structuralVerticalSprings, idSpring, structuralSpringColor, STRUCTURAL_VERTICAL);

            if(added)
            {
                idSpring = idSpring + 1;
            }

            pBegin = p3;

            pEnd = p4;

            added = createSpring(pBegin, pEnd, &structuralHorizontalSprings, idSpring, structuralSpringColor, STRUCTURAL_HORIZONTAL);

            if(added)
            {
                idSpring = idSpring + 1;
            }

            pBegin = p4;

            pEnd = p1;

            added = createSpring(pBegin, pEnd, &structuralVerticalSprings, idSpring, structuralSpringColor, STRUCTURAL_VERTICAL);

            if(added)
            {
                idSpring = idSpring + 1;
            }

            //cisalhamento
            pBegin = p1;

            pEnd = p3;

            added = createSpring(pBegin, pEnd, &shearSprings, idSpring, shearSpringColor, SHEAR);

            if(added) idSpring = idSpring + 1;

            pBegin = p2;

            pEnd = p4;

            added = createSpring(pBegin, pEnd, &shearSprings, idSpring, shearSpringColor, SHEAR);

            if(added) idSpring = idSpring + 1;

			continue;
		}
		else if(type == "#")
		{
		    //comentarios
			//Comments!
			stream.readLine();

			continue;
		}
		else if(type == "mtllib")
        {
		    //informacao do arquivo
			//Comments!
			stream.readLine();

			continue;
		}
		else if(type == "usemtl")
		{
		    //informacao do arquivo
			//Comments!
			stream.readLine();

			continue;
		}
		else if(type == "s")
        {
            //informacao do arquivo
			//Comments!
			stream.readLine();

			continue;
		}
		else if(type == "o")
        {
            //informacao do arquivo
			//Comments!
			stream.readLine();

			continue;
		}
	}



    Spring *otherS;
    Particle *otherMBegin, *otherMEnd;
	//criando as molas de flexão

	if(_adjacency == EIGHT_ADJACENCY)
	{
        for(unsigned int i = 0; i < shearSprings.size(); i++)
        {
            s = shearSprings.at(i);

            pBegin = particles.at(s->getParticleBegin());

            pEnd = particles.at(s->getParticleEnd());

            for(unsigned int j = 0; j < shearSprings.size(); j++)
            {
                otherS = shearSprings.at(j);

                if (otherS == s) continue;

                otherMBegin = particles.at(otherS->getParticleBegin());

                otherMEnd = particles.at(otherS->getParticleEnd());

                if(otherMBegin == pEnd)
                {
                    added = createSpring(pBegin, otherMEnd, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }
                else if(otherMEnd == pEnd)
                {
                    added = createSpring(pBegin, otherMBegin, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }


                if(otherMBegin == pBegin)
                {
                    added = createSpring(pEnd, otherMEnd, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }
                else if(otherMEnd == pBegin)
                {
                    added = createSpring(pEnd, otherMBegin, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }

            }
        }
	}else
	{
        for(unsigned int i = 0; i < structuralHorizontalSprings.size(); i++)
        {
            s = structuralHorizontalSprings.at(i);

            pBegin = particles.at(s->getParticleBegin());

            pEnd = particles.at(s->getParticleEnd());

            for(unsigned int j = 0; j < structuralHorizontalSprings.size(); j++)
            {
                otherS = structuralHorizontalSprings.at(j);

                if (otherS == s) continue;

                otherMBegin = particles.at(otherS->getParticleBegin());

                otherMEnd = particles.at(otherS->getParticleEnd());

                if(otherMBegin == pEnd)
                {
                    added = createSpring(pBegin, otherMEnd, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }
                else if(otherMEnd == pEnd)
                {
                    added = createSpring(pBegin, otherMBegin, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }


                if(otherMBegin == pBegin)
                {
                    added = createSpring(pEnd, otherMEnd, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }
                else if(otherMEnd == pBegin)
                {
                    added = createSpring(pEnd, otherMBegin, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }

            }
        }

        for(unsigned int i = 0; i < structuralVerticalSprings.size(); i++)
        {
            s = structuralVerticalSprings.at(i);

            pBegin = particles.at(s->getParticleBegin());

            pEnd = particles.at(s->getParticleEnd());

            for(unsigned int j = 0; j < structuralVerticalSprings.size(); j++)
            {
                otherS = structuralVerticalSprings.at(j);

                if (otherS == s) continue;

                otherMBegin = particles.at(otherS->getParticleBegin());

                otherMEnd = particles.at(otherS->getParticleEnd());

                if(otherMBegin == pEnd)
                {
                    added = createSpring(pBegin, otherMEnd, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }
                else if(otherMEnd == pEnd)
                {
                    added = createSpring(pBegin, otherMBegin, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }


                if(otherMBegin == pBegin)
                {
                    added = createSpring(pEnd, otherMEnd, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }
                else if(otherMEnd == pBegin)
                {
                    added = createSpring(pEnd, otherMBegin, &flexionSprings, idSpring, flexionSpringColor, FLEXION);

                    if(added) idSpring = idSpring + 1;
                }

            }
        }
	}


    //juntando todas as molas em uma unica lista

	std::vector<Spring *> springs;

	springs.insert(springs.end(), structuralVerticalSprings.begin(), structuralVerticalSprings.end());

	springs.insert(springs.end(), structuralHorizontalSprings.begin(), structuralHorizontalSprings.end());

	springs.insert(springs.end(), shearSprings.begin(), shearSprings.end());

	springs.insert(springs.end(), flexionSprings.begin(), flexionSprings.end());


	std::vector<Fabric *> fabrics;

	fabrics.push_back(new Fabric(idFabric++, particles, springs, faces, dof, toMatrixNx3(idParticle, refVector), hasTextureCoord));

	return fabrics;
}

std::vector<Fabric *> *Input::playbackParse()
{
    if(!playbackFabrics.empty()){
        for(unsigned int i = 0; i < playbackFabrics.size(); i++){
            if(playbackFabrics.at(i)) delete playbackFabrics.at(i);
        }
        playbackFabrics.clear();
    }

    playbackEnd = false;

	QString type;

	std::vector<Particle *> particles;

	std::vector<Spring *> springs;

	std::vector<Face *> faces;

//    std::vector<Fabric *> fabrics;

    bool hasTextureCoord = false;

	unsigned int idParticle = 0;

	unsigned int idFabric = 0;

	unsigned int idSpring = 0;

	unsigned int idFace = 0;

    streamPlayback.seek(0);
    streamPlayback.setDevice(playbackFile);

	bool canAddFabric = false;

	while(streamPlayback >> type, !streamPlayback.atEnd())
	{
		if(type == "c")
		{
		    //adiciona logo na lista caso tenha mais de um tecido
		    if(canAddFabric) playbackFabrics.push_back(new Fabric(idFabric++, particles, springs, faces, hasTextureCoord));

		    unsigned int id, totalParticles;
			streamPlayback >> id >> totalParticles;

			particles.clear();
			faces.clear();
			springs.clear();

			idParticle = 0;
            idFabric = 0;
            idSpring = 0;
            idFace = 0;

			for(unsigned int i = 0; i < totalParticles; i++)
			{
			    particles.push_back(new Particle(i));
			}
			canAddFabric = true;

			continue;
		}
		else if(type == "x")
        {
		    double u, v;
			streamPlayback >> u >> v;

			Particle *p = particles.at(idParticle++);
			p->setTextureCoord(u, v);

			hasTextureCoord = true;

			continue;
		}
		else if(type == "s")
        {
		    unsigned int springType, particleBegin, particleEnd;
			streamPlayback >> springType >> particleBegin >> particleEnd;

            springs.push_back(new Spring(idSpring++, springType, particleBegin, particleEnd));

			continue;
		}
		else if(type == "f")
        {
            unsigned int v1, v2, v3;
			streamPlayback >> v1 >> v2 >> v3;

			Particle *p1 = particles.at(v1);
			Particle *p2 = particles.at(v2);
			Particle *p3 = particles.at(v3);

            Face *f = new Face(idFace++);
            f->addParticle(p1);
            f->addParticle(p2);
            f->addParticle(p3);

            p1->addFace(f);
            p2->addFace(f);
            p3->addFace(f);

            faces.push_back(f);

			continue;
		}
		else if(type == "#")
		{
		    //comentarios
			//Comments!
			streamPlayback.readLine();

			continue;
		}
		else if(type == "t")
		{
            unsigned int id;
            //os tecidos ja adicionados
            for(unsigned int j = 0; j < idFabric; j++)
            {
                streamPlayback >> id >> timeInPlayback;
                std::vector<Particle *> particles_ = playbackFabrics.at(id)->getParticles();
                for(unsigned int i = 0; i < particles_.size(); i++)
                {
                    double x, y, z;
                    streamPlayback >> x >> y >> z;
                    particles_[i]->setPosition(Vector3D(x, y, z));
                }
            }

            //o ultimo tecido, que não ainda não foi adicionado a lista


            streamPlayback >> id >> timeInPlayback;
            for(unsigned int i = 0; i < particles.size(); i++)
            {
                double x, y, z;
                streamPlayback >> x >> y >> z;
                particles[i]->setPosition(Vector3D(x, y, z));
            }



            //ler logo o proximo tempo ***
            streamPlayback >> id >> timeInPlayback;
			break;
		}
	}
    //assim que se apertar play, relamente ler o arquivo


    //adiciona o ultimo tecido criado
    if(canAddFabric) playbackFabrics.push_back(new Fabric(idFabric++, particles, springs, faces, hasTextureCoord));


    for(unsigned int i = 0; i < idFabric; i++)
    {
        playbackFabrics[i]->updateState();
    }

	return &playbackFabrics;
}

Matrix Input::toMatrixNx3(unsigned int _n, std::vector<int> _refVector)
{
	Matrix result(_n, 3);

	int k = 0;
	for(unsigned int i = 0; i < _n; i++)
	{
        for(int j = 0; j < 3; j++)
        {
            result[i][j] = _refVector.at(k++);
        }
	}

	return result;
}

bool Input::createSpring(Particle *_pBegin, Particle *_pEnd, std::vector<Spring *> *_springVector, unsigned int _id, const Color &_springColor, unsigned int _type)
{
    Spring *s = new Spring(_id, _type, _pBegin, _pEnd, _springColor);

    Spring *otherS;
    for(unsigned int i = 0; i < _springVector->size(); i++)
    {
        otherS = _springVector->at(i);

        if( (otherS->getParticleBegin() == _pBegin->getID() && otherS->getParticleEnd() == _pEnd->getID()) || (otherS->getParticleBegin() == _pEnd->getID() && otherS->getParticleEnd() == _pBegin->getID())) return false;
    }

    _springVector->push_back(s);
    _pBegin->addSpring(s);
    _pEnd->addSpring(s);
    return true;
}

void Input::startPlayback()
{
    if(!playbackFile) return;
    if(playbackEnd){
        playbackParse();
    }
    else{
        connect(timer, SIGNAL(timeout()), this, SLOT(updatePlayback()));
        updatePlayback();
    }
}

void Input::pausePlayback()
{
    timer->disconnect(SIGNAL(timeout()));
}

void Input::stopPlayback()
{
    timer->disconnect(SIGNAL(timeout()));
    playbackEnd = true;
    startPlayback();
}

void Input::updatePlayback()
{
    unsigned int id = 0;
    char t;
    double newTimeInPlayback, deltaInPlayback = 0;
    for(unsigned int j = 0; j < playbackFabrics.size(); j++)
    {
        if(j != 0) streamPlayback >> id >> timeInPlayback;

        std::vector<Particle *> particles = playbackFabrics.at(id)->getParticles();
        for(unsigned int i = 0; i < particles.size(); i++)
        {
            double x, y, z;
            streamPlayback >> x >> y >> z;
            particles[i]->setPosition(Vector3D(x, y, z));

        }
        if(!streamPlayback.atEnd()) streamPlayback >> t >> t; //ler o \n e o t
        playbackFabrics[j]->updateState();

    }

    if(!streamPlayback.atEnd()) {
        streamPlayback >> id >> newTimeInPlayback;
        deltaInPlayback = newTimeInPlayback - timeInPlayback;
        timeInPlayback = newTimeInPlayback;
    }else{
        playbackEnd = true;
        pausePlayback();
        emit playbackEnded();
        return;
    }

    //Isso pode dar errado, caso os tecidos tenham tempo de atualização diferentes
    timer->start(deltaInPlayback*1000);
}
